package org.one.stone.soup.grfxML;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;

import org.one.stone.soup.grfx.ImageFactory;
import org.one.stone.soup.math.IntMath;
import org.one.stone.soup.mjdb.data.field.BoolField;
import org.one.stone.soup.mjdb.data.field.FloatField;
import org.one.stone.soup.mjdb.data.field.IntField;
import org.one.stone.soup.mjdb.data.field.LockException;
import org.one.stone.soup.mjdb.data.field.Point2DField;
import org.one.stone.soup.xml.XmlElement;
  /*
 * Copyright 2000-2001 Wet-Wired.com Ltd.,
 * Portsmouth England
 * All rights reserved.
 */

/**
	*
	* @author Nik Cross
*/
public class GeometryText extends Geometry{

	DataPoint windowField;
	DataPoint boundsField;

	DataColor colorField;
	Color color;

	BoolField visibleField;

	FloatField transparencyField;
	boolean transparent;

	BoolField borderField;
	DataColor borderColorField;
	Color borderColor;
	BoolField filledField;
	DataColor fillColorField;
	Color fillColor;

	Point2DField positionField;
	Point2DField offsetField;
	int positionX;
	int positionY;


	IntField rotationField;

	DataText textField;
	String[] text;

	DataSize lineHeightField;
	int lineHeight;

	DataFont fontField;
	Font font;
	FontMetrics fontMetrics;
	Graphics graphics;
	int fontSize;

	BoolField editableField;
	BoolField focusField;

	int width;
	int height;
	int lastWidth;
	int textMargin;
	int textHeight;

	Image renderedImg;

	int flashCount=0;

	Point2DField endOfTextField;
	Point2DField topRightField;
	Point2DField bottomLeftField;
	Point2DField bottomRightField;
	boolean recalc = false;
public GeometryText(
		GrfxMLEngine engine,
		DataPoint windowF,
		DataPoint boundsF,
		BoolField visibleF,
		FloatField transparencyF,
		DataColor colorF,
		BoolField filledF,
		DataColor fillColorF,
		BoolField borderF,
		DataColor borderColorF,
		Point2DField positionF,
		IntField rotationF,
		Point2DField offsetF,
		DataText textF,
		DataFont fontF,
		BoolField editableF,
		BoolField focusF,
		Point2DField	bottomRightF,
		Point2DField	bottomLeftF,
		Point2DField	topRightF,
		Point2DField	endOfTextF,
		DataSize		lineHeightF
) {
	super(engine);

	windowField = windowF;
	boundsField = boundsF;
	visibleField = visibleF;
	transparencyField = transparencyF;
	colorField = colorF;
	filledField = filledF;
	fillColorField = fillColorF;
	borderField = borderF;
	borderColorField = borderColorF;

	rotationField = rotationF;
	positionField = positionF;
	offsetField = offsetF;

	textField = textF;
	fontField = fontF;

	bottomRightField = bottomRightF;
	bottomLeftField = bottomLeftF;
	topRightField = topRightF;
	endOfTextField = endOfTextF;
	lineHeightField = lineHeightF;

	editableField = editableF;
	focusField = focusF;

	process(true);
}
/**
 * contains method comment.
 */
public boolean contains(Point2DField point,Point2DField pointView) {

	int x= pointView.getValueX();
	int y= pointView.getValueY();

	if(
		x<=positionX+width && y<=positionY+height &&
		x>=positionX && y>=positionY
	)
		return true;
	else
		return false;
}
public void draw(Graphics grfx)
{
 try{
	if(visibleField.getValue()==false || transparencyField.getValue()==1)
		return;

	if(visibleField.hasChanged())
	{
		process(true);
	}
	else
	{
		process(false);
	}

	if(
		positionX>engine.BASE.SETTINGS.frameSize.getValueX() ||
		positionY>engine.BASE.SETTINGS.frameSize.getValueY()
	)
	return;

	grfx.setClip(
		windowField.getValueXMin(),
		windowField.getValueYMin(),
		windowField.getValueX(),
		windowField.getValueY()
	);

	if(filledField.getValue()==true)
	{
		grfx.setColor(fillColor);
		grfx.fillRect(positionX,positionY,width,height);
	}

	grfx.setColor(color);
	grfx.setFont(font);
	fontMetrics = grfx.getFontMetrics(font);
	graphics = grfx;

	lineHeight = fontMetrics.getHeight();
	try{
		lineHeightField.setValue(lineHeight,this);
	}catch(LockException le){}//dummy catch
	textHeight = fontMetrics.getAscent();
	textMargin = fontMetrics.getDescent();

	if( !(grfx instanceof Graphics2D) )
	{
		drawFast(grfx);
	}
	else
	{
		Graphics2D grfx2D = (Graphics2D)grfx;

		if( grfx2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING)==RenderingHints.VALUE_ANTIALIAS_ON )
		{
			drawQuality(grfx2D);
		}
		else
		{
			drawFast(grfx2D);
		}
	}

	if(recalc)
	{
		recalc();
	}

	if(borderField.getValue()==true)
	{
		grfx.setColor(borderColor);
		grfx.drawRect(positionX,positionY,width,height);
	}

	if(editableField.getValue()==true)
	{
		flashCount++;
		if(flashCount>8)
		{
			drawCursor(grfx);
		}

		if(flashCount>=20)
			flashCount=0;
	}
 }
catch(Exception e)
{
	e.printStackTrace();
}
	//grfx.setClip(0,0,APIInterface.getEngine().BASE.SETTINGS.frameSize.getValueX(),APIInterface.getEngine().BASE.SETTINGS.frameSize.getValueY());
}

private void drawQuality(Graphics2D grfx)
{
	//Object hint = grfx.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
	if(text==null)
	{
		return;
	}

	width=0;
	height=0;
	lastWidth=0;
	grfx.setColor(color);
	grfx.setFont(font);

	if(font.getSize()<12)
	{
		//grfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	}
	else
	{
		//grfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	}

	grfx.rotate( IntMath.A_TO_R*rotationField.getValue(),positionX,positionY );

	for(int loop=0;loop<text.length;loop++)
	{
		grfx.drawString(text[loop],positionX+textMargin,positionY+height+textHeight);
		height+=lineHeight;

		lastWidth = fontMetrics.stringWidth(text[loop]);
		if(lastWidth>width)
		{
			width = lastWidth;
		}
	}

	grfx.rotate( -(IntMath.A_TO_R*rotationField.getValue()),positionX,positionY );

	lastWidth += (textMargin*2);
	width += (textMargin*2);

	//grfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,hint);
}

public FontMetrics getFontMetrics()
{
	return fontMetrics;
}

public Graphics getGraphicsContext()
{
	return graphics;
}

private void drawFast(Graphics grfx)
{
	if(text==null)
	{
		return;
	}

	if(renderedImg==null)
	{
		width=0;
		height=0;
		lastWidth=0;
		for(int loop=0;loop<text.length;loop++)
		{
			/*if(fontSize>4)
			{
				grfx.drawString(text[loop],positionX+textMargin,positionY+height+textHeight);
			}*/
			height+=lineHeight;

			lastWidth = fontMetrics.stringWidth(text[loop]);
			if(lastWidth>width)
			{
				width = lastWidth;
			}
		}

		lastWidth += (textMargin*2);
		width += (textMargin*2);

		//APInterface.getToolkit().
		if(width==0 || height==0)
		{
			return;
		}
		renderedImg = engine.view.createImage(width,height);
		//renderedImg = ImageFactory.createImage(Color.blue,width,height,APInterface.getToolkit());

		Graphics rGrfx = renderedImg.getGraphics();

		if(color.equals(Color.black))
		{
			rGrfx.setColor(Color.white);
			rGrfx.fillRect(0,0,width,height);
			renderedImg = ImageFactory.makeColorTransparent(renderedImg,Color.white);
		}
		else
		{
			rGrfx.setColor(Color.black);
			rGrfx.fillRect(0,0,width,height);
			renderedImg = ImageFactory.makeColorTransparent(renderedImg,Color.black);
		}


		width=0;
		height=0;
		lastWidth=0;
		rGrfx.setColor(color);
		rGrfx.setFont(font);

		for(int loop=0;loop<text.length;loop++)
		{
			//if(fontSize>4)
			//{
				rGrfx.drawString(text[loop],textMargin,height+textHeight);
			//}
			height+=lineHeight;

			lastWidth = rGrfx.getFontMetrics(font).stringWidth(text[loop]);
			if(lastWidth>width)
			{
				width = lastWidth;
			}
		}
		lastWidth += (textMargin*2);
		width += (textMargin*2);
	}
	/*if(fontSize<=4)
	{
		grfx.fillRect(positionX+textMargin,positionY,width,height);
	}*/
	grfx.drawImage(renderedImg,positionX,positionY,ImageFactory.DUMMY);
	width = renderedImg.getWidth(ImageFactory.DUMMY);
	height = renderedImg.getHeight(ImageFactory.DUMMY);

}

/**
 *
 * @param grfx java.awt.Graphics
 */
public void drawCursor(Graphics grfx)
{
// draw cursor

	if(focusField.getValue()==true)
	{
		grfx.setColor(Color.green);
	}
	else
	{
		grfx.setColor(Color.gray);
	}
	int x1 = positionX+lastWidth-4;
	int y1 = positionY+( lineHeight*(text.length-1) )+1;
	int y2 = y1+lineHeight-3;
	grfx.drawLine(x1,y1,x1,y2);
	grfx.drawLine(x1+1,y1,x1+1,y2);
	grfx.drawLine(x1-2,y1,x1+2,y1);
	grfx.drawLine(x1-2,y2,x1+2,y2);
}
private void process(boolean forced)
{
	recalc = false;
	if(editableField.getValue()==true && focusField.getValue()==true)
	{
		try{
			processTyping();
		}
		catch(LockException le){}//dummy catch
	}

	if(forced==true)
	{
		color = GrfxMLProcessor.getColorFor(colorField);
		fillColor = GrfxMLProcessor.getColorFor(fillColorField);
		borderColor = GrfxMLProcessor.getColorFor(borderColorField);

		positionX = positionField.getValueX();
		positionY = positionField.getValueY();

		positionX += offsetField.getValueX();
		positionY += offsetField.getValueY();

		int fontStyle = 0;
		String style = fontField.style.getValue();
		if(style.indexOf("BOLD")>-1)
			fontStyle += Font.BOLD;
		if(style.indexOf("ITALIC")>-1)
			fontStyle += Font.ITALIC;

		fontSize = fontField.pointSizeView.getValue();
		font = new Font(fontField.face.getValue(),fontStyle,fontSize);

		if(textField.hasChanged() || positionField.hasChanged() || offsetField.hasChanged())
		{
			text = new String[textField.size()];
			for(int loop=0;loop<textField.size();loop++)
			{
				text[loop] = textField.get(loop).getValue();
			}
			renderedImg = null;
		}
		recalc=true;
	}
	else
	{
		if(colorField.hasChanged())
		{
			color = GrfxMLProcessor.getColorFor(colorField);
		}

		if(fillColorField.hasChanged())
		{
			fillColor = GrfxMLProcessor.getColorFor(fillColorField);
		}

		if(borderColorField.hasChanged())
		{
			borderColor = GrfxMLProcessor.getColorFor(borderColorField);
		}

		if(positionField.hasChanged() || offsetField.hasChanged())
		{
			positionX = positionField.getValueX();
			positionY = positionField.getValueY();

			positionX += offsetField.getValueX();
			positionY += offsetField.getValueY();
		}

		if(textField.hasChanged() || positionField.hasChanged() || offsetField.hasChanged())
		{
			text = new String[textField.size()];
			for(int loop=0;loop<textField.size();loop++)
			{
				text[loop] = textField.get(loop).getValue();
			}

			renderedImg=null;
			recalc=true;
			textField.resetChanged();

		}

		if(fontField.hasChanged())
		{
			int fontStyle = 0;
			String style = fontField.style.getValue();
			if(style.indexOf("BOLD")>-1)
				fontStyle += Font.BOLD;
			if(style.indexOf("ITALIC")>-1)
				fontStyle += Font.ITALIC;
			fontSize = fontField.pointSizeView.getValue();
			font = new Font(fontField.face.getValue(),fontStyle,fontSize);
			recalc=true;
		}

	}
}
private void recalc()
{
	try{
		bottomRightField.setValueX(offsetField.getValueX()+width,this);
		bottomRightField.setValueY(offsetField.getValueY()+height,this);

		bottomLeftField.setValueX(offsetField.getValueX(),this);
		bottomLeftField.setValueY(offsetField.getValueY()+height,this);

		topRightField.setValueX(width,this);
		topRightField.setValueY(0,this);

		endOfTextField.setValueX(lastWidth,this);
		endOfTextField.setValueY(height-lineHeight,this);

		boundsField.setValueXMin(positionX+textMargin);
		boundsField.setValueYMin(positionY);

		boundsField.setValueXMax(positionX+textMargin+width);
		boundsField.setValueYMax(positionY+height);

		boundsField.update();
	}
	catch(LockException le){}//dummy catch
}
private void processTyping() throws LockException
{
	if(
		!engine.BASE.KEY.keyBuffer.hasChanged()
	)
		return;

	int key;
	byte[] dataBytes = engine.BASE.KEY.keyBuffer.getValue().getBytes();

	for(int loop=0;loop<dataBytes.length;loop++)
	{
		key = dataBytes[loop];
		if(key==-1)
			continue;

		DataString tag;
		String data;

		switch(key)
		{
			case 10: // return
				textField.add( new DataString(),this );
				break;

			case 8: // delete
				tag = (DataString)textField.get( textField.size()-1 );
				data = tag.getValue();

				if(data.length()==0)
				{
					if( textField.size()>1)
						textField.remove(tag,this);
				}
				else
				{
					data = data.substring(0,data.length()-1);
					tag.setValue(data,this);
				}
				break;
			case 9: // tab
					tag = (DataString)textField.get( textField.size()-1 );
					tag.setValue(
						tag.getValue() +
						"    "
						,this
					);
					break;

			default:
				if(key>=32)
				{
					if(textField.size()==0)
					{
						textField.add(new DataString(),this);
					}
					tag = (DataString)textField.get( textField.size()-1 );
					tag.append((char)key);
				}
			}
	}

	try{
		engine.BASE.KEY.keyBuffer.setValue("",this);
	}
	catch(LockException le){}//dummy catch

	engine.BASE.KEY.keyBuffer.resetChanged();
}
/**
 *
 * @return java.lang.String
 */
public String toString() {
	return super.toString()+": "+textField.togrfxML("text");
}
/**
 *
 * @return java.lang.String
 */
public XmlElement toXML() {
	XmlElement element = new XmlElement("Text");

	if(getId()!=null)
		element.addAttribute("id",getId());

	element.addAttribute("visible",""+visibleField.getValue());
	element.addAttribute("transparency",""+transparencyField.getValue());

	element.addAttribute("x",""+positionX);
	element.addAttribute("y",""+positionY);

	element.addAttribute("width",""+width);
	element.addAttribute("height",""+height);

	element.addAttribute("lineHeight",""+lineHeight);
	element.addAttribute("margin",""+textMargin);

	element.addAttribute("red",""+colorField.getValueX());
	element.addAttribute("green",""+colorField.getValueY());
	element.addAttribute("blue",""+colorField.getValueZ());

	element.addAttribute("filled",""+filledField.getValue());
	XmlElement fillColor = element.addChild("fillColor");
	fillColor.addAttribute("red",""+fillColorField.getValueX());
	fillColor.addAttribute("green",""+fillColorField.getValueY());
	fillColor.addAttribute("blue",""+fillColorField.getValueZ());

	element.addAttribute("border",""+filledField.getValue());
	XmlElement borderColor = element.addChild("borderColor");
	borderColor.addAttribute("red",""+borderColorField.getValueX());
	borderColor.addAttribute("green",""+borderColorField.getValueY());
	borderColor.addAttribute("blue",""+borderColorField.getValueZ());

	XmlElement textE = element.addChild("text");
	textE.addAttribute("fontFace",fontField.getFace().getValue());
	textE.addAttribute("fontSize",""+fontSize);
	for(int loop=0;loop<text.length;loop++)
	{
		textE.addValue(text[loop]);
	}

	XmlElement bounds = element.addChild("Clip");
	bounds.addAttribute( "x",""+windowField.getValueXMin() );
	bounds.addAttribute( "y",""+windowField.getValueYMin() );
	bounds.addAttribute( "width",""+windowField.getValueX() );
	bounds.addAttribute( "height",""+windowField.getValueY() );

	return element;
}

public boolean hasChanged()
{
	if(
	        windowField.hasChanged()==true ||
	        boundsField.hasChanged()==true ||
	        visibleField.hasChanged()==true ||
	        transparencyField.hasChanged()==true ||
	        colorField.hasChanged()==true ||
	        filledField.hasChanged()==true ||
	        positionField.hasChanged()==true ||
	        offsetField.hasChanged()==true ||
	        positionField.hasChanged()==true ||
	        offsetField.hasChanged()==true ||
	        textField.hasChanged()==true ||
	        fontField.hasChanged()==true
	)
	{
	    return true;
	}
	
	return false;
}

public void resetChanged()
{
    windowField.resetChanged();
    boundsField.resetChanged();
    visibleField.resetChanged();
    transparencyField.resetChanged();
    colorField.resetChanged();
    filledField.resetChanged();
    positionField.resetChanged();
    offsetField.resetChanged();
    positionField.resetChanged();
    offsetField.resetChanged();
    textField.resetChanged();
    fontField.resetChanged();
}

}
